﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Data;
using AdaptiveAgents.Distributions;

namespace AdaptiveAgents.Loggers
{
    public class XmlLogger : Logger
    {
        private String fileName;
        private StreamWriter fout;
        private DataSet _dataset;
        private readonly string GAME_DETAILS = "GameDetails";
        private readonly string PLAYERS_DETAILS = "PlayersDetails";
        private readonly string GAME_MOVES = "GameMoves";
        private int _numOfPlayers = 0;

        public XmlLogger(String name)
        {
            fileName = name;

            try
            {
                // Open a file stream writer
                fout = new StreamWriter(fileName);
            }
            // Catches any error conditions
            catch (IOException e)
            {
                System.Console.Error.WriteLine("Unable to write to game analyzer file: " + fileName);
                System.Diagnostics.Debug.Assert(false);
            }

            //Create a new dataset and initialize it's tables
            _dataset = new System.Data.DataSet("GameDataSet");

            _dataset.Tables.Add(createGameDetailsTable());
            _dataset.Tables.Add(createPlayersDetailsTable());
        }

        private DataTable createGameDetailsTable()
        {
            DataTable dt = new DataTable(GAME_DETAILS);
            dt.Columns.Add("NumberOfPlayers", typeof(int));
            dt.Columns.Add("GameType", typeof(string));

            return dt;
        }

        private DataTable createPlayersDetailsTable()
        {
            DataTable dt = new DataTable(PLAYERS_DETAILS);
            dt.Columns.Add("Epsilon", typeof(string));
            dt.Columns.Add("Distribution", typeof(string));
            //dt.Columns.Add("IDistribution", typeof(IDistribution));

            return dt;
        }

        private DataTable createGameMovesTable(int numOfPlayers)
        {
            DataTable dt = new DataTable(GAME_MOVES);
            dt.Columns.Add("Performence", typeof(string));
            dt.Columns.Add("ActivePlayer", typeof(int));
            dt.Columns.Add("ActiveDecider", typeof(int));

            for (int i = 0; i < numOfPlayers; ++i)
            {
                dt.Columns.Add("Agent" + i, typeof(double));
                dt.Columns.Add("Expected" + i, typeof(double));
            }

            return dt;
        }

        protected override void writeInternal(MessageType message, bool newLine, params object[] data)
        {
            bool isWrite = true;

            switch (message)
            {
                case MessageType.Turn:
                    printTurn((Turn)data[0]);
                    break;
                case MessageType.AgentAttributes:
                    printAgentAttributes((double)data[0], (IDistribution)data[1]);
                    break;
                case MessageType.GameDetails:
                    _numOfPlayers = int.Parse(data[0].ToString());
                    _dataset.Tables[GAME_DETAILS].Rows.Add(_numOfPlayers, data[1]);
                    _dataset.Tables.Add(createGameMovesTable(int.Parse(data[0].ToString())));
                    break;
                default:
                    isWrite = false;
                    break;
            }
        }

        private void printAgentAttributes(double epsilon, IDistribution dist)
        {
            _dataset.Tables[PLAYERS_DETAILS].Rows.Add(epsilon, dist.ToString());
        }

        private void printTurn(Turn turn)
        {
            DataRow row = _dataset.Tables[GAME_MOVES].NewRow();
            row["ActivePlayer"] = turn.ActivePlayer; //Print active player
            row["ActiveDecider"] = turn.ActiveDecider; //Print active decider
            row["Performence"] = turn.Performence; //Print performence of active player

            for (int i = 0; i < _numOfPlayers; ++i)
            {
                row["Agent" + i] = Math.Round(turn.EstimatedCompetences[i], 3);
                row["Expected" + i] = turn.getExpectedAct(i);
                
            }
            _dataset.Tables[GAME_MOVES].Rows.Add(row);

           /*     DataTable dt = new DataTable(GAME_MOVES);
            dt.Columns.Add("Performance", typeof(string));
            dt.Columns.Add("ActivePlayer", typeof(int));
            dt.Columns.Add("ActiveDecider", typeof(int));

            for (int i = 0; i < numOfPlayers; ++i)
            {
                dt.Columns.Add("Agent" + i, typeof(double));
                dt.Columns.Add("Estimated" + i, typeof(double));
            }*/


            //Print estimated competence of each player
            
            
            
        }

        public override void Close()
        {
            try
            {
                //fout.Close();
                fout.Write(_dataset.GetXml());
                fout.Flush();
                fout.Close();
            }
            catch (IOException e)
            {
                System.Console.Error.WriteLine("Problem closing file: " + fileName);
            }
        }
    }
}
